use crate::configure::CONF;
use serde::{Deserialize, Serialize};

static SECRET: &str = "secret";

#[derive(Serialize, Deserialize, Debug)]
pub struct JwtToken {
    pub username: String,
    exp: i64,
}

impl JwtToken {
    fn get_secret() -> String {
        CONF.get_string("jwt.secret")
            .unwrap_or_else(|_| SECRET.to_string())
    }
    pub fn new(username: String) -> Self {
        let timeout = CONF.get_int("jwt.timeout").unwrap_or_else(|_| 60 * 60 * 24);
        Self::new_with_timeout(username, timeout)
    }
    pub fn new_with_timeout(username: String, timeout: i64) -> Self {
        let now = chrono::Local::now().timestamp();
        Self {
            username,
            exp: now + timeout,
        }
    }
    pub fn create_token(&self) -> anyhow::Result<String> {
        let token = jsonwebtoken::encode(
            &jsonwebtoken::Header::default(),
            &self,
            &jsonwebtoken::EncodingKey::from_secret(Self::get_secret().as_bytes()),
        )?;
        Ok(token)
    }
    pub fn decode_token(token: &str) -> anyhow::Result<Self> {
        let mut validation = jsonwebtoken::Validation::default();
        validation.leeway = 1;
        
        let token = jsonwebtoken::decode::<JwtToken>(
            token,
            &jsonwebtoken::DecodingKey::from_secret(Self::get_secret().as_bytes()),
            &validation,
        )?;
        Ok(token.claims)
    }
}
